package Phase2Tests;
 

import org.junit.Assert;
import org.junit.Test;

import java.util.Collection;
import java.util.ArrayList;
import java.util.Random;

import Phase2.Node; 
import Phase2.NodeList;

public class testNode
{
	@Test
	public void testNodeList() throws InterruptedException
	{
		Node root = new Node();
		
		NodeList temp = new NodeList();

		Assert.assertEquals(0, temp.size()); 
		//System.out.println(temp.toString());
		Node tempNode = new Node();
		root.insert(tempNode);
		temp.add(tempNode);
		Assert.assertEquals(1, temp.size());
		//System.out.println(temp.toString());

		tempNode = new Node();
		root.insert(tempNode);
		temp.add(tempNode);
		Assert.assertEquals(2, temp.size());

		tempNode = new Node();
		root.insert(tempNode);
		temp.add(tempNode);
		Assert.assertEquals(3, temp.size());

		tempNode = new Node();
		root.insert(tempNode);
		temp.add(tempNode);
		Assert.assertEquals(4, temp.size());
		Assert.assertEquals(4, temp.getMax().getId(false));
		
		System.out.println("testNodeList PASSED!");
	}
	@Test
	public void testAddNode() throws InterruptedException
	{
		Node root = new Node();
		root.insert(new Node());
	//	System.out.println(root.toString());
		root.insert(new Node());
	//	System.out.println(root.toString());
		
		root.insert(new Node());
	//	System.out.println(root.toString());
		root.insert(new Node());
	//	System.out.println(root.toString());
		root.insert(new Node());
	//	System.out.println(root.toString());
	//	System.out.println("\n\n\n\n" + root.getFold().toString());
		System.out.println("testAddNode PASSED!");
	}
	@Test
	public void testAddNodes() throws InterruptedException
	{
		Node root = new Node();
		root.insert(new Node());
		root.insert(new Node()); 
		root.insert(new Node());
		root.insert(new Node());
		root.insert(new Node());
		root.insert(new Node()); 
		root.insert(new Node()); 
	 //	System.out.print(root.printAllNode());
		System.out.println("testAddNodes PASSED!");
	}
	/*
	public void testGetLast()
	{
		Node[] nodeList = {new Node(), new Node(), new Node(), new Node(), new Node(),
				new Node(), new Node(), new Node(), new Node(), new Node(), new Node(), new Node(), new Node()};
		
		Node root = nodeList[0];
		
		for(int i = 1; i <= 12; i++)
		{
			root.insert(nodeList[i]);
		}
		
		Assert.assertEquals(root.getLastNode().getId(), 12); 
	}
	
	public void testGetLast2()
	{
		Node root = new Node();
		root.insert(new Node());
		root.insert(new Node()); 
		root.insert(new Node());
		root.insert(new Node());
		root.insert(new Node());
		Node temp = new Node();
		root.insert(temp); 
		root.insert(new Node());
		root.insert(new Node());
		root.insert(new Node());
		root.insert(new Node()); 
		root.insert(new Node());
		root.insert(new Node());

		Assert.assertEquals(temp.getLastNode().getId(), 12); 
	}
	*/
	@Test
	public void testRemoveSize() throws InterruptedException
	{
		Node root = new Node();
		root.insert(new Node());
		root.insert(new Node()); 
		root.insert(new Node());
		root.insert(new Node());
		root.insert(new Node());
		root.insert(new Node());
		root.insert(new Node());
		root.insert(new Node());
		root.insert(new Node()); 
		root.insert(new Node());
		root.insert(new Node());
		Node temp = new Node();
		root.insert(temp);
		//System.out.println(root.printAllNode());
		temp.remove();
		//System.out.println(root.printAllNode());
		//Assert.assertEquals(11, root.getLastNode().getId()); 
		
		System.out.println("testRemoveSize PASSED!");			
	}
	@Test
	public void testRemoveSize2() throws InterruptedException
	{
		Node root = new Node();
		root.insert(new Node());
		root.insert(new Node()); 
		root.insert(new Node());
		root.insert(new Node());
		root.insert(new Node());
		root.insert(new Node());
		root.insert(new Node());
		root.insert(new Node());
		root.insert(new Node()); 
		root.insert(new Node());
		root.insert(new Node());
		Node temp = new Node();
		root.insert(temp);
		Node temp1 = new Node();
		root.insert(temp1);
		temp1.remove();
		temp.remove();
		//Assert.assertEquals(11, root.getLastNode().getId()); 
		System.out.println("testRemoveSize2 PASSED!");
	}
	@Test
	public void testRemoveNode1() throws InterruptedException
	{
		Node root = new Node();
		root.insert(new Node());
		root.insert(new Node()); 
		root.insert(new Node());
		root.insert(new Node()); 
		root.insert(new Node());
		Node temp = new Node(); 
		String part1 = root.printAllNode();
		root.insert(temp);  
		//String result = root.printAllNode();
		temp.remove();
		String other = root.printAllNode();
		
		//System.out.println("\n" + part1  + "\n" + result + "\n\n\n\n"+other);
		Assert.assertEquals(part1, other); 
		System.out.println("testRemoveNode1 PASSED!");
	}
	@Test
	public void testRemoveNode2() throws InterruptedException
	{
		Node root = new Node();
		root.insert(new Node());
		root.insert(new Node());  
		root.insert(new Node());
		Node temp = new Node(); 
		String part1 = root.printAllNode();
		root.insert(temp);  
		//String result = root.printAllNode();
		temp.remove();
		String other = root.printAllNode();
		//System.out.println("\n" + part1  + "\n" + result + "\n\n\n\n"+other);
		
		Assert.assertEquals(part1, other); 
		System.out.println("testRemoveNode2 PASSED!");
	}
	@Test
	public void testRemoveNode3() throws InterruptedException
	{
		Node root = new Node();
		root.insert(new Node());  
		  	
		for(int i = 0; i < 100; i++)
		{
			Node temp = new Node();
			String part1 = root.printAllNode();
			root.insert(temp);
			temp.remove();
			String part2 = root.printAllNode();
			root.insert(new Node());
			//Assert.assertEquals(part1,part2); 
			if(!part1.equals(part2))
			{
				System.out.println("\npart1:" + part1 + "\n\npart2:" + part2);
				break;
			}
			 
		}
		System.out.println("testRemoveNode3 PASSED!");
	}
	 
	 
	@Test
	public void fullRemoveTest() throws InterruptedException
	{
		System.out.println("fuleRemoveTest of 64 nodes starting...");
		
		ArrayList<String> webState = new ArrayList<String>();
		ArrayList<Node> nodes = new ArrayList<Node>();
		
		// making the original HyPeerWeb and storing the state
		// at each addition
		Node root = new Node();
		nodes.add(root);
		webState.add(root.printAllNode());		
		Node temp = new Node();
		
		for (int i = 1; i < 64; i++)
		{
			temp = new Node();
			root.insert(temp);
			webState.add(root.printAllNode());
			nodes.add(temp);
		}
		
		for (int i = 62; i >= 0; i--)
		{
			int index = randomIndex(nodes); 
			nodes.remove(index).remove();
			//root.getNeighbours().getMax().remove();
			Assert.assertEquals(webState.get(i), nodes.get(0).printAllNode());
		}
		
		for (int j = 0; j < 5; j++)
		{
			System.out.println("fullRemoveTest Pass " + (j + 1));
			root = nodes.get(0);
			
			for (int i = 1; i < 64; i++)
			{
				temp = new Node();
				root.insert(temp);
				nodes.add(temp);
			}
			
			System.out.print("Nodes removed in order: ");
			for (int i = 62; i >= 0; i--)
			{
				int index = randomIndex(nodes); 
				nodes.remove(index).remove();
				//root.getNeighbours().getMax().remove();
				Assert.assertEquals(webState.get(i), nodes.get(0).printAllNode());
				System.out.print(index + " ");
			}
			System.out.println("");

		}
		
		
		
		System.out.println("fullRemoveTest PASSED!");
	}
	
	private static int randomIndex(Collection<?> c)
	{
		Random generator = new Random(System.currentTimeMillis());				
		return generator.nextInt(c.size() - 1);
	}
	
}
